#include <stdlib.h>
#include <string.h>
#include "ota_log.h"
#include "ota_hal_os.h"
#include "aos/hal/flash.h"
#include "ota_hal_param.h"

static ota_boot_param_t ota_param_flash;

int ota_is_download_mode(void)
{
    int ret = 0;
    ota_boot_param_t param = {0};
    memset(&param, 0, sizeof(ota_boot_param_t));
    ret = ota_read_parameter(&param);
    if(ret < 0) {
         return 0;
    }
    if((param.upg_status == OTA_TRANSPORT) && (param.upg_flag != 0xffff)){
         OTA_LOG_I("OTA running status :0x%04x \n",param.upg_status);
         return 1;
    }
    OTA_LOG_I("ota is status:%d  param crc:0x%04x \n",param.upg_status, param.param_crc);
    return ret;
}

int ota_read_parameter(ota_boot_param_t *ota_param)
{
    int ret = OTA_UPGRADE_PARAM_FAIL;
    int param_part = HAL_PARTITION_PARAMETER_1;
    unsigned int offset = 0;
    unsigned short patch_crc = 0;
    if(ota_param == NULL) {
        return ret;
    }
    memset(ota_param, 0, sizeof(ota_boot_param_t));
    memcpy(ota_param, &ota_param_flash, sizeof(ota_boot_param_t));
#if 0
    ret = hal_flash_read(param_part, &offset, ota_param, sizeof(ota_boot_param_t));
    if(ret < 0) {
        return ret;
    }
    patch_crc = ota_get_data_crc16((const unsigned char *)ota_param, sizeof(ota_boot_param_t) - sizeof(unsigned short));
    OTA_LOG_I("ota param crc:0x%04x cal:0x%04x \n", ota_param->param_crc, patch_crc);
    if(patch_crc == ota_param->param_crc) {
        return 0;
    }
#endif
    return 0;
}

int ota_parameter_save(ota_boot_param_t *ota_param)
{
    int ret = OTA_UPGRADE_PARAM_FAIL;
    ota_boot_param_t comp_buf;
    unsigned int offset = 0x00;
    unsigned int len = sizeof(ota_boot_param_t);

    if (NULL != ota_param)
    {
        memcpy(&ota_param_flash, ota_param, sizeof(ota_boot_param_t));
    }
    ota_param_flash.param_crc = ota_get_data_crc16(&ota_param_flash, sizeof(ota_boot_param_t) - sizeof(unsigned short));
    OTA_LOG_I("ota update param crc:0x%04x flag:0x%04x \n", ota_param_flash.param_crc, ota_param_flash.upg_flag);
    memset(&comp_buf, 0, sizeof(ota_boot_param_t));
    ret = hal_flash_dis_secure(HAL_PARTITION_PARAMETER_1, 0, 0);
    if(ret != 0) {
        return OTA_UPGRADE_PARAM_FAIL;
    }
    ret = hal_flash_erase(HAL_PARTITION_PARAMETER_1, offset, len);
    if (ret != 0)
    {
        OTA_LOG_I("ota param erase fial ");
        return OTA_UPGRADE_PARAM_FAIL;
    }

    ret = hal_flash_write(HAL_PARTITION_PARAMETER_1, &offset, &ota_param_flash, len);
    if (ret != 0)
    {
        OTA_LOG_I("ota param write fial ");
        return OTA_UPGRADE_PARAM_FAIL;
    }
    offset = 0x00;

    ret = hal_flash_read(HAL_PARTITION_PARAMETER_1, &offset, (unsigned char*)&comp_buf, len);
    if (ret != 0)
    {
        OTA_LOG_I("ota param write fial ");
        return OTA_UPGRADE_PARAM_FAIL;
    }

    if(memcmp(&ota_param_flash, (unsigned char*)&comp_buf, len) != 0) 
    {
        OTA_LOG_I("ota param check fial ");
        return OTA_UPGRADE_PARAM_FAIL;

    }

    return 0;
}


int ota_update_parameter(ota_boot_param_t *ota_param)
{
    int ret = OTA_UPGRADE_PARAM_FAIL;

    if(ota_param == NULL) {
        return ret;
    }
    
    memcpy(&ota_param_flash, ota_param, sizeof(ota_boot_param_t));
    ota_param_flash.param_crc = ota_get_data_crc16(&ota_param_flash, sizeof(ota_boot_param_t) - sizeof(unsigned short));
    return 0;
}

int ota_get_image_size(void)
{
    int ret = 0;
    int size = 0;
    ota_boot_param_t ota_param = {0};
    ret = ota_read_parameter(&ota_param);
    if(ret < 0) {
        return ret;
    }
    size = ota_param.len;
    return size;
}

int ota_update_image_size(unsigned int size)
{
    int ret = 0;
    ota_boot_param_t ota_param = {0};
    OTA_LOG_I("image size:%d \n", size);
    ret = ota_read_parameter(&ota_param);
    if(ret < 0) {
        return ret;
    }
    ota_param.len = size;
    ret = ota_update_parameter(&ota_param);
    return 0;
}

unsigned short ota_get_upgrade_flag(void)
{
    int ret = 0;
    unsigned short flag = 0;
    ota_boot_param_t ota_param = {0};
    ret = ota_read_parameter(&ota_param);
    if(ret < 0) {
        return 0xffff;
    }
    flag = ota_param.upg_flag;
    return flag;
}

int ota_update_upg_flag(unsigned short flag)
{
    int ret = 0;
    ota_boot_param_t ota_param = {0};
    OTA_LOG_I("upg_flag:0x%x \n", flag);
    ret = ota_read_parameter(&ota_param);
    if(ret < 0) {
        return ret;
    }
    ota_param.upg_flag = flag;
    ret = ota_update_parameter(&ota_param);
    return 0;
}

int ota_get_image_version(char* ver)
{
    int ret = 0;
    ota_boot_param_t ota_param = {0};
    if(ver == NULL || strlen(ver) >= OTA_VER_LEN) {
        return OTA_TRANSPORT_PAR_FAIL;
    }
    ret = ota_read_parameter(&ota_param);
    if(ret < 0) {
        return ret;
    }
    strncpy(ver, ota_param.ver, strlen(ota_param.ver));
    return ret;
}

int ota_update_image_version(char *ver)
{
    int ret = 0;
    ota_boot_param_t ota_param = {0};
    if(ver == NULL || strlen(ver) >= OTA_VER_LEN) {
        return OTA_TRANSPORT_PAR_FAIL;
    }
    OTA_LOG_I("image version:%s \n", ver);
    ret = ota_read_parameter(&ota_param);
    if(ret < 0) {
        return ret;
    }

    strncpy(ota_param.ver, ver, strlen(ver));
    ota_param.ver[strlen(ver)] = '\0';
    ret = ota_update_parameter(&ota_param);
    return ret;
}
